import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; import "react-loading-skeleton/dist/skeleton.css"; import { ChevronDownIcon, ClockIcon, HeartIcon, } from "@heroicons/react/20/solid"; import { TvIcon, ArrowTrendingUpIcon, RectangleStackIcon, } from "@heroicons/react/24/outline"; import Head from "next/head"; import Image from "next/image"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; import Layout from "../../../components/layout"; import Link from "next/link"; import Content from "../../../components/home/content"; import Modal from "../../../components/modal"; import { signIn, useSession } from "next-auth/react"; import AniList from "../../../components/media/aniList"; import ListEditor from "../../../components/listEditor"; import { GET_MEDIA_USER } from "../../../queries"; import { GET_MEDIA_INFO } from "../../../queries"; import { ToastContainer } from "react-toastify"; // import { aniInfo } from "../../components/devComp/data"; // console.log(GET_MEDIA_USER); export default function Info({ info, color, api }) { // Episodes dropdown const [firstEpisodeIndex, setFirstEpisodeIndex] = useState(0); const [lastEpisodeIndex, setLastEpisodeIndex] = useState(); const [selectedRange, setSelectedRange] = useState("All"); function onEpisodeIndexChange(e) { if (e.target.value === "All") { setFirstEpisodeIndex(0); setLastEpisodeIndex(); setSelectedRange("All"); return; } setFirstEpisodeIndex(e.target.value.split("-")[0] - 1); setLastEpisodeIndex(e.target.value.split("-")[1]); setSelectedRange(e.target.value); } const { data: session } = useSession(); const [episode, setEpisode] = useState(null); const [loading, setLoading] = useState(false); const [progress, setProgress] = useState(0); const [statuses, setStatuses] = useState(null); const [domainUrl, setDomainUrl] = useState(""); const [showAll, setShowAll] = useState(false); const [visible, setVisible] = useState(false); const [open, setOpen] = useState(false); const [time, setTime] = useState(0); const { id } = useRouter().query; const [epiView, setEpiView] = useState("3"); const [artStorage, setArtStorage] = useState(null); const rec = info?.recommendations?.nodes?.map( (data) => data.mediaRecommendation ); const [provider, setProvider] = useState(); const [prvValue, setPrvValue] = useState("gogoanime"); const [availableProviders, setAvailableProviders] = useState([]); // const [err, setErr] = useState(''); function handleProvider(e) { setEpisode( Array.isArray(provider[e.target.value]) ? provider[e.target.value]?.reverse() : provider[e.target.value] ); setPrvValue(e.target.value); localStorage.setItem("provider", e.target.value); } //for episodes dropdown useEffect(() => { setFirstEpisodeIndex(0); setLastEpisodeIndex(); setSelectedRange("All"); }, [info, prvValue]); useEffect(() => { handleClose(); async function fetchData() { setLoading(true); if (id) { try { const { protocol, host } = window.location; const prv = localStorage.getItem("provider"); const url = `${protocol}//${host}`; const view = localStorage.getItem("epiView"); if (prv) { setPrvValue(prv); } else { setPrvValue("gogoanime"); } setDomainUrl(url); setArtStorage(JSON.parse(localStorage.getItem("artplayer_settings"))); setEpisode(null); setProgress(0); setStatuses(null); let reloadCount = 0; try { const fetchPromises = [ fetch(`${api}/meta/anilist/info/${info.id}?provider=enime`), fetch(`${api}/meta/anilist/info/${info.id}?provider=zoro`), fetch(`${api}/meta/anilist/info/${info.id}?provider=gogoanime`), ]; const results = await Promise.allSettled(fetchPromises); const successfulResponses = []; let errorCount = 0; results.forEach((result) => { if (result.status === "fulfilled") { successfulResponses.push(result.value); } else { errorCount++; } }); if (errorCount === fetchPromises.length) { // All fetch requests failed, handle the error here setEpisode([]); } else { // Process the successfulResponses here const responsesData = await Promise.all( successfulResponses.map((response) => response.json()) ); const [enime, zoro, gogoanime] = responsesData; const prov = { enime: enime?.episodes || enime, zoro: zoro?.episodes || zoro, gogoanime: gogoanime?.episodes || gogoanime, }; const aPrv = [ { name: "enime", available: enime?.episodes && enime?.episodes.length > 0 ? true : false, }, { name: "zoro", available: zoro?.episodes && zoro?.episodes.length > 0 ? true : false, }, { name: "gogoanime", available: gogoanime?.episodes && gogoanime?.episodes.length > 0 ? true : false, }, ]; setAvailableProviders(aPrv); const infProv = { enime: enime, zoro: zoro, gogoanime: gogoanime, }; if (prv) { setEpisode( Array.isArray(prov[prv]) ? prov[prv]?.reverse() : prov[prv] ); } else { setEpisode( Array.isArray(prov["gogoanime"]) ? prov["gogoanime"]?.reverse() : prov["gogoanime"] ); } const data = infProv[prv] || infProv["gogoanime"]; // const data = aniInfo; if (!data || data?.episodes?.length === 0) { setEpisode([]); } else { if (data.episodes?.some((i) => i.title === null)) { setEpiView("3"); } else if (view) { setEpiView(view); } else { setEpiView("3"); } } if (session?.user?.name) { const response = await fetch("https://graphql.anilist.co/", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ query: GET_MEDIA_USER, variables: { username: session?.user?.name, }, }), }); const responseData = await response.json(); const prog = responseData?.data?.MediaListCollection; if (prog && prog.lists.length > 0) { const gut = prog.lists .flatMap((item) => item.entries) .find((item) => item.mediaId === parseInt(id[0])); if (gut) { setProgress(gut.progress); const statusMapping = { CURRENT: { name: "Watching", value: "CURRENT" }, PLANNING: { name: "Plan to watch", value: "PLANNING" }, COMPLETED: { name: "Completed", value: "COMPLETED" }, DROPPED: { name: "Dropped", value: "DROPPED" }, PAUSED: { name: "Paused", value: "PAUSED" }, REPEATING: { name: "Rewatching", value: "REPEATING" }, }; setStatuses(statusMapping[gut.status]); } } } if (data.nextAiringEpisode) { setTime( convertSecondsToTime(data.nextAiringEpisode.timeUntilAiring) ); } setProvider(prov); } } catch (error) { console.error(error); if (reloadCount < 2) { reloadCount++; setTimeout(() => { window.location.reload(); }, 1000); } else { setEpisode([]); } } } catch (error) { console.error(error); setTimeout(() => { window.location.reload(); }, 1000); } finally { setLoading(false); } } } fetchData(); }, [id, info, session?.user?.name]); function handleOpen() { setOpen(true); document.body.style.overflow = "hidden"; } function handleClose() { setOpen(false); document.body.style.overflow = "auto"; } const filterProviders = availableProviders?.filter((x) => x.available); return ( <> {info ? info?.title?.romaji || info?.title?.english : "Retrieving Data..."} handleClose()}>
{!session && (

Edit your list

)} {session && info && ( )}
{info ? ( banner anime ) : (
)}
{/* Mobile */}

{info?.title?.romaji || info?.title?.english}

{info?.genres ?.slice( 0, info?.genres?.length > 3 ? info?.genres?.length : 3 ) .map((item, index) => ( {item} ))}
{info && (
)}
{info && info.status !== "NOT_YET_RELEASED" ? ( <>

{info?.type}

{info?.averageScore}%

{info?.episodes ? (

{info?.episodes} Episodes

) : (

TBA

)}
) : (
{info && "Not Yet Released"}
)}
{/* PC */}
{info ? ( <>
poster anime ) : ( )}
{/* PC */}

{info ? ( info?.title?.romaji || info?.title?.english ) : ( )}

{info ? (
{info?.episodes && (
{info?.episodes} Episodes
)} {info?.startDate?.year && (
{info?.startDate?.year}
)} {info?.averageScore && (
{info?.averageScore}%
)} {info?.type && (
{info?.type}
)} {info?.status && (
{info?.status}
)}
Sub | EN
) : ( )}
{info ? (

) : ( )}

{info?.relations?.edges?.length > 0 && (
Relations
)} {info?.relations?.edges?.length > 3 && (
setShowAll(!showAll)} > {showAll ? "show less" : "show more"}
)}
{info?.relations?.edges ? ( info?.relations?.edges .slice(0, showAll ? info?.relations?.edges.length : 3) .map((r, index) => { const rel = r.node; return (
{rel.id}
{r.relationType}
{rel.title.userPreferred || rel.title.romaji}
{rel.type}
); }) ) : ( <> {[1, 2, 3].map((item) => (
))}
)}
{info && (

Episodes

)} {info?.nextAiringEpisode && (

Next :

{time}
)}
setVisible(!visible)} >
{filterProviders?.length > 0 && (

Provider

)} {episode?.length > 50 && (

Episodes

)}
0 ? episode?.some((item) => item?.title === null) ? "pointer-events-none" : "cursor-pointer" : "pointer-events-none" } onClick={() => { setEpiView("1"); localStorage.setItem("epiView", "1"); }} > 0 ? episode?.some((item) => item?.title === null) ? "fill-[#1c1c22]" : epiView === "1" ? "fill-action" : "fill-[#3A3A44]" : "fill-[#1c1c22]" }`} rx="3" >
0 ? episode?.some((item) => item?.title === null) ? "pointer-events-none" : "cursor-pointer" : "pointer-events-none" } onClick={() => { setEpiView("2"); localStorage.setItem("epiView", "2"); }} > 0 ? episode?.some((item) => item?.title === null) ? "fill-[#1c1c22]" : epiView === "2" ? "fill-action" : "fill-[#3A3A44]" : "fill-[#1c1c22]" }`} viewBox="0 0 33 20" >
0 ? `cursor-pointer` : "pointer-events-none" } onClick={() => { setEpiView("3"); localStorage.setItem("epiView", "3"); }} > 0 ? epiView === "3" ? "fill-action" : "fill-[#3A3A44]" : "fill-[#1c1c22]" }`} viewBox="0 0 33 20" >
{!loading ? ( Array.isArray(episode) ? ( episode && (
{episode?.length !== 0 && episode ? (
{epiView === "1" ? episode .slice(firstEpisodeIndex, lastEpisodeIndex) ?.map((epi, index) => { const time = artStorage?.[epi?.id]?.time; const duration = artStorage?.[epi?.id]?.duration; let prog = (time / duration) * 100; if (prog > 90) prog = 100; return ( Episode {epi?.number}
epi image ); }) : ""} {epiView === "2" && episode .slice(firstEpisodeIndex, lastEpisodeIndex) .map((epi, index) => { const time = artStorage?.[epi?.id]?.time; const duration = artStorage?.[epi?.id]?.duration; let prog = (time / duration) * 100; if (prog > 90) prog = 100; return (
Anime Cover Episode {epi?.number}

{epi?.title}

{epi?.description && (

{epi?.description}

)}
); })} {epiView === "3" && episode .slice(firstEpisodeIndex, lastEpisodeIndex) .map((epi, index) => { return (

Episode {epi.number}

{epi.title && (

"{epi.title}"

)} {index !== episode?.length - 1 && ( )}
); })}
) : (

No Episodes Available

)}
) ) : (
                        {episode?.message}
                      
) ) : (
)}
{info && rec?.length !== 0 && (
)}
); } export async function getServerSideProps(context) { const { id } = context.query; const API_URI = process.env.API_URI; const res = await fetch("https://graphql.anilist.co/", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ query: GET_MEDIA_INFO, variables: { id: id?.[0], }, }), }); const json = await res.json(); const data = json?.data?.Media; if (!data) { return { notFound: true, }; } const textColor = setTxtColor(data?.coverImage?.color); const color = { backgroundColor: `${data?.coverImage?.color || "#ffff"}`, color: textColor, }; return { props: { info: data, color: color, api: API_URI, }, }; } function convertSecondsToTime(sec) { let days = Math.floor(sec / (3600 * 24)); let hours = Math.floor((sec % (3600 * 24)) / 3600); let minutes = Math.floor((sec % 3600) / 60); let time = ""; if (days > 0) { time += `${days}d `; } if (hours > 0) { time += `${hours}h `; } if (minutes > 0) { time += `${minutes}m `; } return time.trim(); } function getBrightness(hexColor) { if (!hexColor) { return 200; } const rgb = hexColor .match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i) .slice(1) .map((x) => parseInt(x, 16)); return (299 * rgb[0] + 587 * rgb[1] + 114 * rgb[2]) / 1000; } function setTxtColor(hexColor) { const brightness = getBrightness(hexColor); return brightness < 150 ? "#fff" : "#000"; } const getLanguageClassName = (language) => { switch (language) { case "javascript": return "language-javascript"; case "html": return "language-html"; case "bash": return "language-bash"; // add more languages here as needed default: return ""; } };